/*
 * Copyright 2016-2019 yoara
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package yhao.infra.feature.mail.core;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import yhao.infra.common.util.CommonDateUtil;
import yhao.infra.feature.mail.core.entity.Email;
import yhao.infra.feature.mail.core.sender.MailSender;
import yhao.infra.feature.mail.core.sender.MailSenderPool;
import yhao.infra.feature.mail.core.util.VelocityUtil;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 邮件发送处理工具
 *
 * @author yoara
 */
@Service("webBaseMailService")
public class MailService {
	private static final Logger log = LoggerFactory.getLogger(MailService.class);
	private static final int TRY_COUNT = 3;

	/**
	 * 发送邮件
	 */
	public void send(Email email){
		if (StringUtils.isEmpty(email.getSubject())) {
			throw new IllegalArgumentException("mail subject cannot be null");
		}
		if(!email.isText()){
			Map<String, Object> contentModel = makeEmailContentModel(email.getParam());
			//渲染contentTemplateUrl
			email.setContent(VelocityUtil.templateMerge(email.getTemplateCode().getTemplateUrl(), contentModel));
		}
		sendEmailWithPool(email);
	}

	/**
	 * 设置模型参数
	 * @return
	 */
	private Map<String, Object> makeEmailContentModel(Map<String, Object> params){
		Map<String, Object> model = new HashMap<>();
		model.put("currentTime", CommonDateUtil.formatDateToyyyy_MM_dd_HH_mm_ss(new Date()));//当前时间
		if(params != null && params.size()>0){
			model.putAll(params);
		}
		return model;
	}

	/**
	 * 通过轮训机制从邮箱池中发送邮件
	 */
	private void sendEmailWithPool(Email email){
		MailSenderPool pool = MailSenderPool.getMailSenderList(email.getTemplateCode().getSenderKey());
		//发送池size
		int poolSize = pool.getMailSenderList().size();
		//重试次数
		int tryCount = poolSize==1?1:TRY_COUNT;
		//轮询种子
		int seedInt = RandomUtils.nextInt(poolSize)+tryCount;
		while(tryCount>0){
			try{
				MailSender emailSender = pool.getMailSenderList().get(seedInt%poolSize);
				MimeMessage message = getMimeMessage(emailSender,email);
				emailSender.send(message);
				return;
			}catch (MessagingException me){
				log.error(me.getMessage(),me);
				tryCount--;
				seedInt--;
			}
		}
	}

	private MimeMessage getMimeMessage(MailSender emailSender, Email email) throws MessagingException {
		MimeMessage message = emailSender.createMimeMessage();
		MimeMessageHelper helper = new MimeMessageHelper(message, true);

		helper.setFrom(emailSender.getSenderCode());
		//helper.setValidateAddresses(true);
		helper.setText(email.getContent(), !email.isText());
		helper.setSubject(email.getSubject());
		helper.setTo(email.getReceivers());
		if(ArrayUtils.isNotEmpty(email.getCc())){
			helper.setCc(email.getCc());
		}
		if(ArrayUtils.isNotEmpty(email.getBcc())){
			helper.setBcc(email.getCc());
		}
		helper.setSentDate(new Date());

		for(File file : email.getAttachFile()){
			FileSystemResource fileSystemResource = new FileSystemResource(file);
			helper.addAttachment(file.getName(), fileSystemResource);
		}
		return message;
	}
}
